package org.zlb.manager.web;

import static org.zlb.manager.Constant.PUBLIC_KEY;
import static org.zlb.manager.Constant.ZLB_NAME;

import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.zhiqim.kernel.util.DateTimes;
import org.zhiqim.kernel.util.Sqls;
import org.zlb.manager.Result;
import org.zlb.manager.dao.FunAvatarDao;
import org.zlb.manager.entity.FunAvatar;
import org.zlb.manager.entity.FunMenu;
import org.zlb.manager.entity.OrgOperator;
import org.zlb.manager.service.FunMenuService;
import org.zlb.manager.service.FunParamService;
import org.zlb.manager.util.HttpUtil;

/**
 * TODO
 *
 * @author zhoulingbo
 * @date 2021/8/10 9:23
 */
@Controller
public class IndexControl {

    private static final Logger logger = LoggerFactory.getLogger(IndexControl.class);

    @Autowired
    private FunParamService paramService;

    @Autowired
    private FunMenuService menuService;

    @Autowired
    private FunAvatarDao avatarDao;

    @RequestMapping(value = {"/index.html", ""}, method = RequestMethod.GET)
    public String index(Model model) {
        model.addAttribute("publicKey", paramService.item(ZLB_NAME, PUBLIC_KEY).getParamValue());
        return "index";
    }

    @RequestMapping(value = "/main.html", method = RequestMethod.GET)
    public String main(Model model) throws Exception {
        Subject subject = SecurityUtils.getSubject();
        OrgOperator orgOperator = (OrgOperator) subject.getPrincipal();
        Session session = subject.getSession();
        List<FunMenu> menuList = menuService.getOperatorMenuList(orgOperator);
        session.setAttribute("menuList", menuList);

        Map<String, List<FunMenu>> menuMap = menuService.initMenuMap(menuList);
        List<FunMenu> topMenuList = menuList.stream().filter(p->(p.getMenuLevel() == 1 && p.getMenuType() == 1))
                .collect(Collectors.toList());
        List<FunAvatar> avatarList = avatarDao.findAll();
        FunAvatar avatar = avatarList.stream()
                .filter(p->p.getAvatarId() == orgOperator.getOperatorAvatar())
                .findFirst().get();

        model.addAttribute("orgOperator", orgOperator);
        model.addAttribute("menuMap", menuMap);
        model.addAttribute("topMenuList", topMenuList);
        model.addAttribute("avatar", avatar);
        return "iframeMain";
    }

    @RequestMapping(value = "/welcome.html", method = RequestMethod.GET)
    public String welcome(HttpServletRequest httpRequest, Model model) {
    	Subject subject = SecurityUtils.getSubject();
        OrgOperator orgOperator = (OrgOperator) subject.getPrincipal();
        orgOperator.setOperatorIp(HttpUtil.getIPAddress(httpRequest));
        orgOperator.setOperatorModified(Sqls.nowTimestamp());
        
        Runtime rt = Runtime.getRuntime();
        long use = (rt.totalMemory() - rt.freeMemory())  / 1024 / 1024;
        long max = rt.maxMemory()  / 1024 / 1024;
        
        OperatingSystemMXBean system = ManagementFactory.getOperatingSystemMXBean();
        String systemVersion = system.getName() + " " + system.getVersion();
        
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        String pidName = runtime.getName();
        String jdkVersion = runtime.getVmName() + " " + runtime.getVmVersion();
        String startTime = DateTimes.toDateTimeString(runtime.getStartTime());
        long uptime = runtime.getUptime();
        long day = uptime / (24 * 3600 * 1000);
        long hour = (uptime % (24 * 3600 * 1000)) / (3600 * 1000);
        long min = (uptime % (3600 * 1000)) / (60 * 1000);
        long sec = (uptime % (60 * 1000)) / 1000;
 
        model.addAttribute("use", use);
        model.addAttribute("max", max);
        model.addAttribute("pidName", pidName);
        model.addAttribute("systemVersion", systemVersion);
        model.addAttribute("jdkVersion", jdkVersion);
        model.addAttribute("startTime", startTime);
        model.addAttribute("day", day);
        model.addAttribute("hour", hour);
        model.addAttribute("min", min);
        model.addAttribute("sec", sec);
        
    	model.addAttribute("orgOperator", orgOperator);
        return "main";
    }

    @ResponseBody
    @RequestMapping(value = "/login.html", method = RequestMethod.POST)
    public Result<?> login(HttpServletRequest httpServletRequest, HttpServletResponse response,
                        @RequestParam("userName") String userName, @RequestParam("password") String password,
                        @RequestParam("verificationCode") String verificationCode) {
        String verificationCodeIn = (String) httpServletRequest.getSession().getAttribute("verificationCode");
        httpServletRequest.getSession().removeAttribute("verificationCode");
        if (verificationCodeIn == null || !verificationCodeIn.equals(verificationCode)) {
            return Result.failMessage("验证码错误，或已失效");
        }

        String result = login(userName, password);
        if ("登录成功".equals(result)) {
            logger.info("用户:{}登录成功", userName);
            return Result.successMessage("登录成功");
        }
        return Result.failMessage(result);
    }

    private String login(String userName, String password) {
        Subject subject = SecurityUtils.getSubject(); // 从SecurityUtils里边创建一个 subject
        UsernamePasswordToken token = new UsernamePasswordToken(userName, password); // 在认证提交前准备 token（令牌）

        try {
            subject.login(token);
        } catch (AuthenticationException ae) {
            return "用户名或密码不正确！";
        }

        if (subject.isAuthenticated()) {
            return "登录成功";
        } else {
            token.clear();
            return "登录失败";
        }
    }
}
